﻿//C语言标准并未说明cha，是signed还是unsigned 通常取决于编译器



//整型 三种表示方法：原码，反码，补码，整型最高位为符号位，0整1负，对有符号型有效
//正数，原码 反码 补码相同
//负数：原码按二进制翻译出来，反码就是原码按位取反，补码就是反码+1
//内存中存的是补码
//unsigned int a =-10;
//printf("%u\n",a);
//-10的补码要赋给无符号型，或以无符号打印，那么这个数会很大，因为是以-10的补码进行的
//cahar 1000 0001 = -127———— -1 取反 = 1111 1111 = - 127
//则    1000 0000 = -128直接判断    因为全为0，无1可减，所以直接出-128
#include <stdio.h>
//1.判断大小端
//2.char a = -1
// signed char b = -1;
// unsigned char c = -1;
//[rintf("%d,%d,%d\n",a,b,c
//int main()
//{
//	int i =1;
//	char a = -1;
//	printf("%d",i+a);
//}


//1.先按整型写出其二进制补码
//2.在截断
//3.再根据其他操作，按原码打印等，高位按符号位补，符号位是1就补1，无论unsigned还是signed





//*****************************************************************************
/*

int main()
{
	int a = 20;
	int b = -20;
	/*
可以看到对应的补码：
a =  0000 0000  0000 0000  0000 0000  0001 0100 
对应的十六进制   =  00	00	00	14 
b =  1111 1111 1111 1111 1111 1111 1110 1100
对应的十六进制   =  ff	ff	ff	ec 



//说明 整型在二进制中存储是以补码形式进行的
//正数，原码 反码 补码相同
//负数：原码按二进制翻译出来，反码就是原码按位取反，补码就是反码+1

	return 0;

}
*/




//
//int  main()
//{
//	int n = 9;
//	float* pFloat = (float*)&n;		//给谁赋值就转换成谁的类型
//	printf("n的值为：%d\n",n);
//	printf("*pFloat的值为：%f\n",*pFloat);
//	*pFloat = 9.0;
//	printf("n的值为：%d\n",n);
//	printf("*pFloat的值为：%f\n",*pFloat);
//	return 0;
//}

//****************************************************************二级指针相关问题
//#include <stdio.h>
//int main()
//{
//	int i;
//	int arr[] = {1,2,3,4,5,6,7,8,9,0};
//	int** pa;
//	int *p = arr; //指针存放数组首元素的地址
//	int sz = sizeof(arr)/sizeof(arr[0]);
//	pa = &p;
//	for(i=0; i<sz; i++)
//	{
//			printf("&arr[%d] = %p   <====> *pa+%d = %p\n", i, &arr[i], i, pa+i);
//	}
//	return 0;
//}
//
//


/*****************************************************************************原反补的注意事项
#include <stdio.h>
int main()
{
    char a= -1;
    signed char b=-1;
    unsigned char c=-1;
    printf("a=%d,b=%d,c=%d",a,b,c);
    return 0; }

a为字符型，占一个字节其原、反、补如下
由于-1是负数，先按负数处理
原码：10000000 00000000 00000000 00000001	先写出-1的原码
反码：11111111 11111111 11111111 11111110	原码按位取反（除符号位） 
补码：11111111 11111111 11111111 11111111	反码+1
而a是有符号字符型只有一个字节大小，所以发生截断 即 a = 1111 1111 = -1
--------------------------------------------------------------------
b是有符号型，与a同理（在vs的编译器中，char被归为有符号型）
--------------------------------------------------------------------
c是无符号型，其原反补如下
由于-1是负数，先按负数处理
原码：10000000 00000000 00000000 00000001	先写出-1的原码
反码：11111111 11111111 11111111 11111110	原码按位取反得到反码
补码：11111111 11111111 11111111 11111111	反码+1得到补码
c是无符号char型，只占一个字节，所以发生截断 c = 1111 1111 = 255(按无符号存)
-----------------------------------------------------------------------
最后输出时：按的有符号整型打印的

a的结果过程：
先整型提升（有符号型的数，按照符号位高位补1/0）
a = 11111111 11111111 11111111 11111111
打印的是有符号数（原码）
反码：11111111 11111111 11111111 11111110
原码：10000000 00000000 00000000 00000001
最后结果为：-1，b同理

c的结果过程
先整型提升，但是他是以无符号型存储的，所以高位直接补0（无符号型高位直接补0）
补码：00000000 00000000 00000000 11111111
因为符号位为0，所以现在认为他是个正数，原反补相同：最后按有符号整型输出时，符号位为0，所以最后结果为255

总结：
char x/unsigned char x
x>0:原反补相同
x<0:先原码转补码
输出前，先按原数据类型整型提升并补位：	
1.有符号型，按符号位从高位补0\1
2.无符号型，直接高位补0
输出时：
1.%u无论是正是负，直接输出，不用再求原码（%u就认为当前数据是无符号的，正数原反补相同）
2.%d时
（1）若符号位为0，则直接输出（正数原反补相同）
（2）若符号位为1，则要求其原码后输出
*/
/**************************************************************************************************
#include <stdio.h>
int main()
{
    char a = -128;
    printf("%u\n",a);
    return 0; 
}

a<0,先求其原反补
原码：10000000 00000000 00000000 10000000
反码：11111111 11111111 11111111 01111111
补码：11111111 11111111 11111111 10000000
截断 a = 10000000
输出时按照无符号整型：
先整型提升，因为是有符号型，所以高位按符号位补
补码：11111111 11111111 11111111 10000000
因为是%u现在认为该数是无符号数：直接按无符号型输出：4294967168
*/


/**************************************************************************************************
#include <stdio.h>
int main()
{
    char a = 128;
    printf("%u\n",a);
    return 0; 
}
a为正数，但是char有符号的范围是 -127——128 那么会是多少？详解如下
原码：00000000 00000000 00000000 10000000，虽然超范围了，但也只是char型存不下，这里先按int型计算，又因为是正数所以高位补0
原反补相同
发生截断 a = 10000000
输出时，按%u输出
先整型提升补位，因为原数据类型是有符号，而a的最高位是1，所以补1
11111111 11111111 11111111 10000000，而%u把他认为是正数所以直接输出，与例2结果相同
*/
/**************************************************************************************************
int i= -20;
unsigned  int  j = 10;
printf("%d\n", i+j); 

i是小于0的求其原反补
原：10000000 00000000 00000000 00010100
反：11111111 11111111 11111111 11101011
补：11111111 11111111 11111111 11101100
j是大于0的原反补想同
原：00000000 00000000 00000000 00001010

i：11111111 11111111 11111111 11101100
+
j：00000000 00000000 00000000 00001010
=：11111111 11111111 11111111 11110110 ———— 补码
由于i+j符号位是1，且按照有符号整型打印，所以要求原码
反：11111111 11111111 11111111 11110101
原：10000000 00000000 00000000 00001010 = -10
所以结果为-10  
*/
/**************************************************************************************************
unsigned int i;
for(i = 9; i >= 0; i--) 
{
    printf("%u\n",i);
}
输出结果为：死循环
因为i是无符号整型，最小就为0，当i=0时，继续自减，会变成最大值，这样就会导致死循环
*/

/**************************************************************************************************
int main()
{
    char a[1000];
    int i;
    for(i=0; i<1000; i++)
    {
        a[i] = -1-i;
    }
    printf("%d",strlen(a));
    return 0; 
}
输出结果为：255
造成输出的原因：
1.strlen是求有效字节长度，遇到\0结束（统计\0之前的元素）
2.char是有符号型，范围是-128~127
	所以运行结果是从0开始赋值为-1，当i到达127（01111111）继续自增
变为（100000000）也就是-128，继续自增当到11111111时继续自增又变成
00000000，然后继续00000001直到结束
所以一直在0~127，-128~0，一直循环赋值，也就是255个数，所以是255*/

/**************************************************************************************************
unsigned char i = 0;
int main()
{
    for(i = 0;i<=255;i++)
   {
        printf("hello world\n");
   }
    return 0; 
}

无符号char的范围是 0~255，当达到255时，继续自增又变为了0
所以输出结果是死循环
可以想象成下方的形式
00000000 00000000 00000000 11111111 +1
=00000000 00000000 00000001 00000000
*/
/**************************************************************************************************浮点型

int  main()
{
	int n = 9;
	float* pFloat = (float*)&n;
	printf("n的值为：%d\n",n);
	printf("*pFloat的值为：%f\n",*pFloat);
	*pFloat = 9.0;
	printf("n的值为：%d\n",n);
	printf("*pFloat的值为：%f\n",*pFloat);
	return 0;
}

1.n的值为9，没有任何整型提升等变换
-------------------------------------------------------------------------
2.pFloat的值为0（取）
首先看n在二进制中的存储为：00000000 00000000 00000000 00001001
由于指针为指向float型的数据，这时二进制变为
0 00000000 00000000000000000001001 
S=0，正数；E=-126，这时有效数字M不再加上第一位的1，而是还原为0.xxxxx001001 
所以是一个无限接近于0的数字
-------------------------------------------------------------------------
*pFloat = 9.0;后
-------------------------------------------------------------------------
3.（存）
9.0 = 1001.0 = 1.001*2^3 = -1^0 * 1.001*2^3
s=0; E=3+127=130; M=1;
= 0 10000010 00100000000000000000000
再以浮点数输出，还为9.0
-------------------------------------------------------------------------
4.0 10000010 00100000000000000000000以整型输出时；
首先它是正的所以原反补相同，直接输出 1091567616


总结：
存时：符号位1为负0为正，
十进制数字转为二进制时只有23个有效位，第一位有效位必须为M=1，且M舍去
而E是挪了几位（挪了2的几次方）+127（1023）
即 1个符号为+8个指数位E+23个小数点后的有效位 = 32位
如 110.1指数必须变为 1.101*2^2,E = 2+127； M为正数的1，舍去

取时：先判断符号位
指数位不为全1全0时，让原来指数的值减去127（1023）
加上有效数字为M以及后面的23位小数点位
指数全0时是一个无线接近于0的很小的数字
指数全为1时是无穷大的一个正负数
即：取时是除了（指数全0全1）怎么存的怎么取
*/



